import os
import time
import xlrd


class Main():
    def __init__(self):
        pass

    def ReadData(self, path):
        if path == None or path == "": return
        self.workbook = xlrd.open_workbook(filename=path)
        tableName = self.GetFirstSheetNameFromExcelFileName(path, 1)


        dt = self.workbook.sheet_by_name(tableName)

        self.CreateData(path, dt)

    def CreateData(self, path, dt):
        pass
        filePath = os.path.dirname(path)
        fileFullName = os.path.basename(path)
        fileName = fileFullName.split(".")[0]

        buffer = None
        dataArr = None

        row = dt.nrows
        column = dt.ncols

        dataArr = []

        for i in range(0, column):
            rowData = []
            for j in range(0, row):
                if (j < 3):
                    rowData.append(dt[j][i].value.strip())
            dataArr.append(rowData)

        self.CreateEntity(filePath, fileName, dataArr)
        self.CreateDBModel(filePath, fileName, dataArr)

    def CreateEntity(self, filePath, fileName, dataArr):
        if (dataArr == None): return

        if not os.path.isdir(f"{filePath}/Create"):
            os.makedirs(f"{filePath}/Create")
        if not os.path.isdir(f"{filePath}/CreateLua"):
            os.makedirs(f"{filePath}/CreateLua")
        if not os.path.isdir(f"{filePath}/CreateJava"):
            os.makedirs(f"{filePath}/CreateJava")

        sbr = ""
        sbr += ("\n")
        sbr += ("//===================================================\n")
        sbr += ("//作    者：边涯  http://www.u3dol.com  QQ群：87481002\n")
        sbr += (f"//创建时间：{time.strftime('%Y-%m-%d %H:%M:%S')}\n")
        sbr += ("//备    注：此代码为工具生成 请勿手工修改\n")
        sbr += ("//===================================================\n")
        sbr += ("using System.Collections;\n")
        sbr += ("\n")
        sbr += ("/// <summary>\n")
        sbr += (f"/// {fileName}实体\n")
        sbr += ("/// </summary>\n")
        sbr += (f"public partial class {fileName}Entity : AbstractEntity\n")
        sbr += ("{\n")

        for i in range(0, len(dataArr)):
            if (i == 0): continue
            sbr += ("    /// <summary>\n")
            sbr += (f"    /// {dataArr[i][2]}\n")
            sbr += ("    /// </summary>\n")
            sbr += ("    public {0} {1} {{ get; set; }}\n".format(dataArr[i][1], dataArr[i][0]))
            sbr += ("\n")

        sbr += ("}\n")

        with open(f"{filePath}/Create/{fileName}Entity.cs", "w+", encoding='UTF-8') as fs:
            fs.write(sbr)

        # region 创建Lua的实体

        sbrLua = ""
        sbrLua += ("{0}Entity = {{ ".format(fileName))

        for i in range(0, len(dataArr)):
            if (i == len(dataArr) - 1):
                if (dataArr[i][1] == "string"):
                    sbrLua += ("{0} = \"\"".format(dataArr[i][0]))
                else:
                    sbrLua += ("{0} = 0".format(dataArr[i][0]))
            else:

                if (dataArr[i][1] == "string"):
                    sbrLua += ("{0} = \"\", ".format(dataArr[i][0]))
                else:
                    sbrLua += ("{0} = 0, ".format(dataArr[i][0]))

        sbrLua += (" }\n")

        sbrLua += ("\n")
        sbrLua += ("--这句是重定义元表的索引，就是说有了这句，这个才是一个类\n")
        sbrLua += ("{0}Entity.__index = {0}Entity;\n".format(fileName))
        sbrLua += ("\n")
        sbrLua += ("function {0}Entity.New(".format(fileName))
        for i in range(0, len(dataArr)):

            if (i == len(dataArr) - 1):

                sbrLua += ("{0}".format(dataArr[i][0]))

            else:

                sbrLua += ("{0}, ".format(dataArr[i][0]))

        sbrLua += (")\n")
        sbrLua += ("    local self = { }; --初始化self\n")
        sbrLua += ("")
        sbrLua += ("    setmetatable(self, {0}Entity) --将self的元表设定为Class\n".format(fileName))
        sbrLua += ("\n")
        for i in range(0, len(dataArr)):
            sbrLua += ("    self.{0} = {0};\n".format(dataArr[i][0]))

        sbrLua += ("\n")
        sbrLua += ("    return self;\n")
        sbrLua += ("end")

        with open(f"{filePath}/CreateLua/{fileName}Entity.lua", "w+", encoding='UTF-8') as fs:
            fs.write(sbrLua)
        # endregion

        sbrJava = "package com.mcx.modules.data.localdata.create;\n"
        sbrJava += ("\n")
        sbrJava += "import com.mcx.modules.data.base.AbstractEntity;"
        sbrJava += ("import lombok.Data;\n")
        sbrJava += ("\n")
        sbrJava += (f"@Data\n")
        sbrJava += (f"public class {fileName}Entity extends AbstractEntity {{\n")

        for i in range(0, len(dataArr)):
            if (i == 0): continue
            sbrJava += (f"    /** {dataArr[i][2]} */\n")
            sbrJava += ("    public {0} {1};\n".format(self.ToJavaType(dataArr[i][1]), dataArr[i][0]))
            sbrJava += ("\n")

        sbrJava += ("}\n")

        with open(f"{filePath}/CreateJava/{fileName}Entity.java", "w+", encoding='UTF-8') as fs:
            fs.write(sbrJava)

    def CreateDBModel(self, filePath, fileName, dataArr):
        if (dataArr == None): return

        if not os.path.isdir(f"{filePath}/Create"):
            os.makedirs(f"{filePath}/Create")
        if not os.path.isdir(f"{filePath}/CreateLua"):
            os.makedirs(f"{filePath}/CreateLua")
        if not os.path.isdir(f"{filePath}/CreateJava"):
            os.makedirs(f"{filePath}/CreateJava")

        sbr = ""

        sbr += ("\n")
        sbr += ("//===================================================\n")
        sbr += ("//作    者：边涯  http://www.u3dol.com  QQ群：87481002\n")
        sbr += (f"//创建时间：{time.strftime('%Y-%m-%d %H:%M:%S')}\n")
        sbr += ("//备    注：此代码为工具生成 请勿手工修改\n")
        sbr += ("//===================================================\n")
        sbr += ("using System.Collections;\n")
        sbr += ("using System.Collections.Generic;\n")
        sbr += ("using System;\n")
        sbr += ("\n")
        sbr += ("/// <summary>\n")
        sbr += ("/// {0}数据管理\n".format(fileName))
        sbr += ("/// </summary>\n")
        sbr += ("public partial class {0}DBModel : AbstractDBModel<{0}DBModel, {0}Entity>\n".format(fileName))
        sbr += ("{\n")
        sbr += ("    /// <summary>\n")
        sbr += ("    /// 文件名称\n")
        sbr += ("    /// </summary>\n")
        sbr += ("    protected override string FileName {{ get {{ return \"{0}.data\"; }} }}\n".format(fileName))
        sbr += ("\n")
        sbr += ("    /// <summary>\n")
        sbr += ("    /// 创建实体\n")
        sbr += ("    /// </summary>\n")
        sbr += ("    /// <param name=\"parse\"></param>\n")
        sbr += ("    /// <returns></returns>\n")
        sbr += ("    protected override {0}Entity MakeEntity(GameDataTableParser parse)\n".format(fileName))
        sbr += ("    {\n")
        sbr += ("        {0}Entity entity = new {0}Entity()\n".format(fileName))

        for i in range(len(dataArr)):
            sbr += ("        entity.{0} = parse.GetFieldValue(\"{0}\"){1};\n".format(dataArr[i][0],
                                                                                     self.ChangeTypeName(dataArr[i][1])))
        sbr += ("        return entity;\n")
        sbr += ("    }\n")
        sbr += ("}\n")

        with open(f"{filePath}/Create/{fileName}DBModel.cs", "w+", encoding='UTF-8') as fs:
            fs.write(sbr)

        # region 生成lua的DBModel

        sbrLua = ""
        sbrLua += ("")

        sbrLua += ("require \"Download/XLuaLogic/Data/Create/{0}Entity\"\n".format(fileName))
        sbrLua += ("\n")
        sbrLua += ("--数据访问\n")
        sbrLua += ("{0}DBModel = {{ }}\n".format(fileName))
        sbrLua += ("\n")
        sbrLua += ("local this = {0}DBModel;\n".format(fileName))
        sbrLua += ("\n")
        sbrLua += ("local {0}Table = {{ }}; --定义表格\n".format(fileName.lower()))
        sbrLua += ("\n")
        sbrLua += ("function {0}DBModel.New()\n".format(fileName))
        sbrLua += ("    return this;\n")
        sbrLua += ("end\n")
        sbrLua += ("\n")
        sbrLua += ("function {0}DBModel.Init()\n".format(fileName))
        sbrLua += ("\n")
        sbrLua += ("    --这里从C#代码中获取一个数组\n")
        sbrLua += ("\n")
        sbrLua += ("    local gameDataTable = CS.LuaHelper.Instance:GetData(\"{0}.data\")\n".format(fileName))
        sbrLua += ("")
        sbrLua += ("    --表格的前三行是表头 所以获取数据时候 要从 3 开始\n")
        sbrLua += ("    --print(\"行数\"..gameDataTable.Row)\n")
        sbrLua += ("    --print(\"列数\"..gameDataTable.Column)\n")
        sbrLua += ("\n")
        sbrLua += ("    for i = 3, gameDataTable.Row - 1, 1 do\n")
        sbrLua += ("        {0}Table[#{0}Table+1] = {1}Entity.New( ".format(fileName.lower(), fileName))

        for i in range(0, len(dataArr)):
            if (i == len(dataArr) - 1):

                if (dataArr[i][1] == "string"):

                    sbrLua += (f"gameDataTable.Data[i][{i}]")
                else:
                    sbrLua += (f"tonumber(gameDataTable.Data[i][{i}])")
            else:
                if (dataArr[i][1] == "string"):
                    sbrLua += (f"gameDataTable.Data[i][{i}], ")
                else:
                    sbrLua += (f"tonumber(gameDataTable.Data[i][{i}]), ")
        sbrLua += (" )\n")
        sbrLua += ("    end\n")
        sbrLua += ("\n")
        sbrLua += ("end\n")
        sbrLua += ("\n")
        sbrLua += ("function {0}DBModel.GetList()\n".format(fileName))
        sbrLua += ("    return {0}Table;\n".format(fileName.lower()))
        sbrLua += ("end")
        sbrLua += ("\n")
        sbrLua += ("\n")
        sbrLua += ("function {0}DBModel.GetEntity(id)\n".format(fileName))
        sbrLua += ("    local ret = nil;\n")
        sbrLua += ("    for i = 1, #{0}Table, 1 do\n".format(fileName.lower()))
        sbrLua += ("        if ({0}Table[i].Id == id) then\n".format(fileName.lower()))
        sbrLua += ("            ret = {0}Table[i];\n".format(fileName.lower()))
        sbrLua += ("            break;\n")
        sbrLua += ("        end\n")
        sbrLua += ("    end\n")
        sbrLua += ("    return ret;\n")
        sbrLua += ("end")

        with open(f"{filePath}/CreateLua/{fileName}DBModel.lua", "w+", encoding='UTF-8') as fs:
            fs.write(sbrLua)
        # endregion

        sbrJava = ""

        sbrJava += ("package com.mcx.modules.data.localdata.create;\n")
        sbrJava += ("\n")
        sbrJava += ("import com.mcx.modules.data.GameDataTableParser;\n")
        sbrJava += ("import com.mcx.modules.data.base.AbstractDBModel;\n")
        sbrJava += ("\n")
        sbrJava += ("/** {0}数据管理 */\n".format(fileName))
        sbrJava += ("public class {0}DBModel extends AbstractDBModel<{0}DBModel, {0}Entity>\n".format(fileName))
        sbrJava += "{\n"
        sbrJava += (F"    private static {fileName}DBModel instance;\n")
        sbrJava += ("\n")
        sbrJava += F"    public static {fileName}DBModel getInstance() {{\n"
        sbrJava += "        if (instance == null) {\n"
        sbrJava += "            instance = new {0}DBModel();\n".format(fileName)
        sbrJava += "        }\n"
        sbrJava += "        return instance;\n"
        sbrJava += "    }\n\n"
        sbrJava += "    /** 文件名称 */\n"
        sbrJava += ("    @Override\n")
        sbrJava += ("    protected String FileName() {\n")
        sbrJava += ("        return \"{0}.data\";\n".format(fileName))
        sbrJava += ("    }\n\n")
        sbrJava += ("    /** 创建实体 */\n")
        sbrJava += ("    @Override\n")
        sbrJava += ("    protected {0}Entity MakeEntity(GameDataTableParser parse)\n".format(fileName))
        sbrJava += "    {\n"
        sbrJava += ("        {0}Entity entity = new {0}Entity();\n".format(fileName))

        for i in range(len(dataArr)):
            sbrJava += ("        entity.{0} = parse.GetFieldValueTo{1}(\"{0}\");\n".format(dataArr[i][0],
                                                                                     self.ChangeTypeName(
                                                                                         dataArr[i][1]).replace('()', '')))
        sbrJava += ("        return entity;\n")
        sbrJava += ("    }\n")
        sbrJava += ("}\n")

        with open(f"{filePath}/CreateJava/{fileName}DBModel.java", "w+", encoding='UTF-8') as fs:
            fs.write(sbrJava)

    def ChangeTypeName(self, type):
        str = ""

        if type=="short":
            str = "Short()"
        elif type=="ushort":
            str = "UShort()"
        elif type=="int":
            str = "Int()"
        elif type=="uint":
            str = "UInt()"
        elif type=="long":
            str = "Long()"
        elif type=="ulong":
            str = "ULong()"
        elif type=="float":
            str = "Float()"
        elif type=="string":
            str = "UTF8String()"
        elif type==   "bool":
            str = "Bool()"
        elif type=="byte":
            str = "Byte()"
        return str

    def ToJavaType(self, type, outType=0):
        str = ""
        str1=""
        if type == "short":
            str = "short"
            str1 = "0"
        elif type == "ushort":
            str = "short"
            str1 = "0"
        elif type == "int":
            str = "Integer"
            str1 = "0"
        elif type == "uint":
            str = "Integer"
            str1 = "0"
        elif type == "long":
            str = "Long"
            str1 = "0"
        elif type == "ulong":
            str = "Long"
            str1 = "0"
        elif type == "float":
            str = "Float"
            str1 = "0"
        elif type == "string":
            str = "String"
            str1 = "\"\""
        elif type == "bool":
            str = "Boolean"
            str1 = "false"
        elif type == "byte":
            str = "byte"
            str1 = "0"

        if (outType == 0):
            return str
        elif (outType == 1):
            return str1
        else:
            return str

    def GetFirstSheetNameFromExcelFileName(self, filepath, numberSheetID):
        if not os.path.exists(filepath): return None

        if (numberSheetID <= 1): numberSheetID = 1

        return self.workbook.sheet_names()[numberSheetID-1]


